﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;

namespace Sofire.DataComm.Net.Async
{
    /// <summary>
    /// 包含套接字的处理。
    /// </summary>
    internal class ReceiveTranslater
    {
        public readonly AsyncSocketBase OwnerAsyncSocket;

        public ReceiveTranslater(AsyncSocketBase ownerAsyncSocket)
        {
            this.OwnerAsyncSocket = ownerAsyncSocket;
        }

        private byte[] Buffer;
        private int LastMessageLength;
        private int LastReadLength;
        private ReceiveMode LastMessageReceiveMode;

        private bool OnFullReceive(SocketAsyncEventArgs from, byte[] buffer, int offset, int count)
        {
            if(this.LastReadLength == 0)
            {
                var messageLength = BufferConvert.ReadInt32(buffer, ref offset);
                count -= 4;

                this.Buffer = new byte[messageLength];
                var messageLessEqualLength = messageLength <= count;

                // ML = 1024, L = 512       长度不够
                if(!messageLessEqualLength)
                {
                    System.Buffer.BlockCopy(buffer, offset, this.Buffer, 0, count);
                    this.LastMessageLength = messageLength;
                    this.LastReadLength = count;
                    return true;
                }

                System.Buffer.BlockCopy(buffer, offset, this.Buffer, 0, messageLength);
              
                // Array.Copy(buffer, offset, this.Buffer, 0, messageLength);
                //   <   ML = 1024 , L = 2048
                //   =   ML = 1024 , L = 1024
                this.FullReceiveCompleted(from, 0, this.Buffer.Length);
                if(messageLength < count)
                {
                    return ProcessReceiveBuffer(from, buffer, offset + messageLength, count - messageLength);
                }

            }
            else
            {
                // ML = 2048, RL = 1024, L = 1024
                //- 还需要读取的长度
                var needReadLength = this.LastMessageLength - this.LastReadLength;


                //- 长度仍然不够
                if(needReadLength > count)
                {
                    System.Buffer.BlockCopy(buffer, offset, this.Buffer, this.LastReadLength, count);
                    this.LastReadLength += count;
                    return true;
                }
                //- 长度够，也可能更多

                System.Buffer.BlockCopy(buffer, offset, this.Buffer, this.LastReadLength, needReadLength);

                this.FullReceiveCompleted(from, 0, this.Buffer.Length);

                if(needReadLength != count)
                {
                    return this.ProcessReceiveBuffer(from, buffer, offset + needReadLength, count - needReadLength);
                }
            }

            return true;
        }

        //- 直接用缓冲区数据。
        private bool OnFullReceive2(SocketAsyncEventArgs from, byte[] buffer, int offset, int count)
        {
            if(this.LastReadLength == 0)
            {
                var messageLength = BufferConvert.ReadInt32(buffer, ref offset);
                count -= 4;

                var messageLessEqualLength = messageLength <= count;

                // ML = 1024, L = 512       长度不够
                if(!messageLessEqualLength)
                {
                    this.Buffer = new byte[messageLength];
                    System.Buffer.BlockCopy(buffer, offset, this.Buffer, 0, count);

                    this.LastMessageLength = messageLength;
                    this.LastReadLength = count;

                    return true;
                }

                this.Buffer = buffer;
                this.FullReceiveCompleted(from, offset, count);
          
                //   <   ML = 1024 , L = 2048
                //   =   ML = 1024 , L = 1024
                if(messageLength < count)
                {
                    return ProcessReceiveBuffer(from, buffer, offset + messageLength, count - messageLength);
                }

            }
            else
            {
                // ML = 2048, RL = 1024, L = 1024
                //- 还需要读取的长度
                var needReadLength = this.LastMessageLength - this.LastReadLength;


                //- 长度仍然不够
                if(needReadLength > count)
                {
                    System.Buffer.BlockCopy(buffer, offset, this.Buffer, this.LastReadLength, count);
                    this.LastReadLength += count;
                    return true;
                }
                //- 长度够，也可能更多

                System.Buffer.BlockCopy(buffer, offset, this.Buffer, this.LastReadLength, needReadLength);

                this.FullReceiveCompleted(from, 0, this.Buffer.Length);

                if(needReadLength != count)
                {
                    return this.ProcessReceiveBuffer(from, buffer, offset + needReadLength, count - needReadLength);
                }
            }

            return true;
        }

        private void FullReceiveCompleted(SocketAsyncEventArgs from, int offset, int count)
        {
            this.OwnerAsyncSocket.RaiseFullReceive(from, this.Buffer, offset, count);
            this.Buffer = null;
            this.LastMessageLength = 0;
            this.LastReadLength = 0;
        }

        private bool OnOnceReceive(SocketAsyncEventArgs from, byte[] buffer, int offset, int count)
        {
            int readLength;
            if(this.LastReadLength == 0)
            {
                var messageLength = BufferConvert.ReadInt32(buffer, ref offset);
                count -= 4;
                var messageLessEqualLength = messageLength <= count;

                if(messageLessEqualLength)
                {
                    readLength = messageLength;
                }
                else
                {
                    // ML = 1024, L = 512       长度不够
                    this.LastMessageLength = messageLength;
                    this.LastReadLength = readLength = count;
                }

                this.OwnerAsyncSocket.RaiseOnceReceive(from, messageLength, readLength, buffer, offset, readLength);
                if(messageLength == count) goto CompletedResult;
                if(messageLength < count) this.ProcessReceiveBuffer(from, buffer, offset + readLength, count - readLength);
                return true;
            }

            readLength = this.LastMessageLength - this.LastReadLength;
            if(readLength > count)
            {
                this.LastReadLength += count;
                this.OwnerAsyncSocket.RaiseOnceReceive(from, this.LastMessageLength, this.LastReadLength, buffer, offset, count);
                return true;
            }
      
            this.OwnerAsyncSocket.RaiseOnceReceive(from, this.LastMessageLength, this.LastReadLength + readLength, buffer, offset, readLength);

            if(readLength == count) goto CompletedResult;

            this.LastReadLength = 0;
            this.LastMessageLength = 0;
            return this.ProcessReceiveBuffer(from, buffer, offset + readLength, count - readLength);

        CompletedResult:
            this.LastReadLength = 0;
            this.LastMessageLength = 0;
            return true;
        }

        /// <summary>
        /// 开始处理异步接收操作。
        /// </summary>
        public bool ProcessReceiveBuffer(SocketAsyncEventArgs from, byte[] buffer, int offset, int count)
        {
            //- 上节无消息，tcp/ip 首包
            if(this.LastMessageLength == 0)
            {
                if(count == 0) return true;
                if(count < 6)
                {
                    this.Buffer = new byte[count];
                    System.Buffer.BlockCopy(buffer, offset, this.Buffer, 0, count);
                    this.LastReadLength = count;
                    return true;
                }
                //使用情形：
                // tcp 发包
                //      包1......
                //      包2......
                // tcp 收包
                //      包1......包2.
                //      .....
                if(this.LastReadLength > 0)
                {
                    var buffer2 = new byte[this.LastReadLength + count];
                    System.Buffer.BlockCopy(this.Buffer, 0, buffer2, 0, this.LastReadLength);
                    System.Buffer.BlockCopy(buffer, offset, buffer2, offset, count);
                    buffer = buffer2;
                    offset = 0;
                    count = buffer2.Length;
                    this.Buffer = null;
                    this.LastReadLength = 0;
                }

                var mode = buffer[offset++];
                count -= 1;
                //- 垃圾包
                if(mode < 1 || mode > 2)
                {
                    //this.OwnerAsyncSocket.RaiseNoneReceive(from, buffer, offset, count);
                    this.Buffer = null;
                    this.LastReadLength = 0;
                    return true;
                }
                this.LastMessageReceiveMode = (ReceiveMode)mode;
            }

            try
            {
                switch(this.LastMessageReceiveMode)
                {
                    case ReceiveMode.Once:
                        return this.OnOnceReceive(from, buffer, offset, count);
                    default:
                        return this.OnFullReceive(from, buffer, offset, count);
                }
            }
            catch(Exception)
            {
                //- 垃圾包
                return false;
            }
        }
    }

}
